﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace UnitSoftware.LINQ2SQLExtentions
{
    public class EntityTypeEventSource
    {
        DataChangeProcessor _processor;

        public event EventHandler<EntityTypeEventArgs> EntityTypeUpdated;
        public event EventHandler<EntityTypeEventArgs> EntityTypeDeleted;
        public event EventHandler<EntityTypeEventArgs> EntityTypeInserted;
        public event EventHandler<EntityTypeOperationEventArgs> EntityTypeOperation;

        public EntityTypeEventSource(DataChangeProcessor processor)
        {
            EntityTypeDeleted += EntityTypeEventSource_EntityTypeDeleted;
            EntityTypeInserted += EntityTypeEventSource_EntityTypeInserted;
            EntityTypeUpdated += EntityTypeEventSource_EntityTypeUpdated;

            _processor = processor;

            processor.EntitiesDeleted += new EventHandler<EntitiesEventArgs>(processor_EntitiesDeleted);
            processor.EntitiesInserted += new EventHandler<EntitiesEventArgs>(processor_EntitiesInserted);
            processor.EntitiesUpdated += new EventHandler<EntitiesEventArgs>(processor_EntitiesUpdated);
        }

        void EntityTypeEventSource_EntityTypeUpdated(object sender, EntityTypeEventArgs e)
        {
            if (EntityTypeOperation != null)
                EntityTypeOperation(this, new EntityTypeOperationEventArgs(Operation.Update, e.Type, e.DataContext));
        }

        void EntityTypeEventSource_EntityTypeInserted(object sender, EntityTypeEventArgs e)
        {
            if (EntityTypeOperation != null)
                EntityTypeOperation(this, new EntityTypeOperationEventArgs(Operation.Insert, e.Type, e.DataContext));
        }

        void EntityTypeEventSource_EntityTypeDeleted(object sender, EntityTypeEventArgs e)
        {
            if (EntityTypeOperation != null)
                EntityTypeOperation(this, new EntityTypeOperationEventArgs(Operation.Delete, e.Type, e.DataContext));
        }

        void processor_EntitiesUpdated(object sender, EntitiesEventArgs e)
        {
            if (EntityTypeUpdated == null)
                return;

            OnEntitiesUpdated(e.Entities, e.DataContext);
        }

        void processor_EntitiesInserted(object sender, EntitiesEventArgs e)
        {
            if (EntityTypeInserted == null)
                return;

            OnEntitiesInserted(e.Entities, e.DataContext);
        }

        void processor_EntitiesDeleted(object sender, EntitiesEventArgs e)
        {
            if (EntityTypeDeleted == null)
                return;

            OnEntitiesDeleted(e.Entities, e.DataContext);
        }

        protected void RaiseEntityTypeUpdated(Type type, DataContext context)
        {
            EntityTypeUpdated(this, new EntityTypeEventArgs(type, context));
        }

        protected void RaiseEntityTypeInserted(Type type, DataContext context)
        {
            EntityTypeDeleted(this, new EntityTypeEventArgs(type, context));
        }

        protected void RaiseEntityTypeDeleted(Type type, DataContext context)
        {
            EntityTypeInserted(this, new EntityTypeEventArgs(type, context));
        }

        protected virtual void OnEntitiesDeleted(IList<object> entities, DataContext context)
        {
            List<Type> typesRaised = new List<Type>();
            Type type;

            foreach (object entity in entities)
                if (!typesRaised.Contains(type = entity.GetType()))
                {
                    typesRaised.Add(type);
                    RaiseEntityTypeDeleted(type, context);
                    return;
                }
        }

        protected virtual void OnEntitiesInserted(IList<object> entities, DataContext context)
        {
            List<Type> typesRaised = new List<Type>();
            Type type;

            foreach (object entity in entities)
                if (!typesRaised.Contains(type = entity.GetType()))
                {
                    typesRaised.Add(type);
                    RaiseEntityTypeInserted(type, context);
                    return;
                }
        }

        protected virtual void OnEntitiesUpdated(IList<object> entities, DataContext context)
        {
            List<Type> typesRaised = new List<Type>();
            Type type;

            foreach (object entity in entities)
                if (!typesRaised.Contains(type = entity.GetType()))
                {
                    typesRaised.Add(type);
                    RaiseEntityTypeUpdated(type, context);
                    return;
                }
        }
    }
}
